﻿
namespace Timo.Common.Extension;

public static class TimeHelper
{
    #region 获得两个日期的间隔
    /// <summary>
    /// 获得两个日期的间隔
    /// </summary>
    /// <param name="date_time1">日期一。</param>
    /// <param name="date_time2">日期二。</param>
    /// <returns>日期间隔TimeSpan。</returns>
    public static TimeSpan DateDiff(DateTime date_time1, DateTime date_time2)
    {
        TimeSpan ts1 = new TimeSpan(date_time1.Ticks);
        TimeSpan ts2 = new TimeSpan(date_time2.Ticks);
        TimeSpan ts = ts1.Subtract(ts2).Duration();
        return ts;
    }
    #endregion

    #region 格式化日期时间
    /// <summary>
    /// 格式化日期时间
    /// </summary>
    /// <param name="date_time1">日期时间</param>
    /// <param name="date_mode">显示模式</param>
    /// <returns>0-9种模式的日期</returns>
    public static string Format(this DateTime date_time1, string date_mode = "1")
    {
        switch (date_mode)
        {
            case "0":
                return date_time1.ToString("yyyy-MM-dd");
            case "1":
                return date_time1.ToString("yyyy-MM-dd HH:mm:ss");
            case "2":
                return date_time1.ToString("yyyy/MM/dd");
            case "3":
                return date_time1.ToString("yyyy年MM月dd日");
            case "4":
                return date_time1.ToString("MM-dd");
            case "5":
                return date_time1.ToString("MM/dd");
            case "6":
                return date_time1.ToString("MM月dd日");
            case "7":
                return date_time1.ToString("yyyy-MM");
            case "8":
                return date_time1.ToString("yyyy/MM");
            case "9":
                return date_time1.ToString("yyyy年MM月");
            default:
                return date_time1.ToString();
        }
    }
    #endregion

    /// <summary>
    /// 获取每月的第一天和最后一天
    /// </summary>
    /// <param name="month"></param>
    /// <param name="firstDay"></param>
    /// <param name="lastDay"></param>
    public static void GetMonthDateFormat(int month, out string firstDay, out string lastDay)
    {
        int year = DateTime.Now.Year + month / 12;
        if (month != 12)
        {
            month = month % 12;
        }
        switch (month)
        {
            case 1:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-0" + month + "-31");
                break;
            case 2:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                if (DateTime.IsLeapYear(DateTime.Now.Year))
                    lastDay = DateTime.Now.ToString(year + "-0" + month + "-29");
                else
                    lastDay = DateTime.Now.ToString(year + "-0" + month + "-28");
                break;
            case 3:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString("yyyy-0" + month + "-31");
                break;
            case 4:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-0" + month + "-30");
                break;
            case 5:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-0" + month + "-31");
                break;
            case 6:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-0" + month + "-30");
                break;
            case 7:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-0" + month + "-31");
                break;
            case 8:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-0" + month + "-31");
                break;
            case 9:
                firstDay = DateTime.Now.ToString(year + "-0" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-0" + month + "-30");
                break;
            case 10:
                firstDay = DateTime.Now.ToString(year + "-" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-" + month + "-31");
                break;
            case 11:
                firstDay = DateTime.Now.ToString(year + "-" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-" + month + "-30");
                break;
            default:
                firstDay = DateTime.Now.ToString(year + "-" + month + "-01");
                lastDay = DateTime.Now.ToString(year + "-" + month + "-31");
                break;
        }
    }

    /// <summary>
    /// 把秒转换成分钟
    /// </summary>
    /// <param name="Second">秒</param>
    /// <returns></returns>
    public static int ToMinute(this int second)
    {
        decimal mm = (decimal)((decimal)second / (decimal)60);
        return Convert.ToInt32(Math.Ceiling(mm));
    }

    #region 返回某年某月最后一天
    /// <summary>
    /// 返回某年某月最后一天
    /// </summary>
    /// <param name="year">年份</param>
    /// <param name="month">月份</param>
    /// <returns>日</returns>
    public static int GetMonthLastDate(int year, int month)
    {
        DateTime last_day = new DateTime(year, month, new System.Globalization.GregorianCalendar().GetDaysInMonth(year, month));
        int Day = last_day.Day;
        return Day;
    }
    #endregion

    #region 返回时间差
    /// <summary>
    /// 计算时间差，返回几秒前几分钟前...
    /// </summary>
    /// <param name="dt_begin">开始时间</param>
    /// <param name="dt_end">结束时间</param>
    /// <returns></returns>
    public static string GetTimeSpanString(this DateTime? dt_begin,DateTime? dt_end = null)
    {
        if (dt_begin is null || dt_begin == default(DateTime))
            return String.Empty;
        if (dt_end is null || dt_end == default(DateTime))
            dt_end = DateTime.Now;
        TimeSpan span = (TimeSpan)(dt_end - dt_begin);
        if (span.TotalDays > 60)
        {
            return ((DateTime)dt_begin).ToShortDateString();
        }
        else
        if (span.TotalDays > 30)
        {
            return "1个月前";
        }
        else
        if (span.TotalDays > 14)
        {
            return "2周前";
        }
        else
        if (span.TotalDays > 7)
        {
            return "1周前";
        }
        else
        if (span.TotalDays > 1)
        {
            return string.Format("{0}天前", (int)Math.Floor(span.TotalDays));
        }
        else
        if (span.TotalHours > 1)
        {
            return string.Format("{0}小时前", (int)Math.Floor(span.TotalHours));
        }
        else
        if (span.TotalMinutes > 1)
        {
            return string.Format("{0}分钟前", (int)Math.Floor(span.TotalMinutes));
        }
        else
        if (span.TotalSeconds >= 1)
        {
            return string.Format("{0}秒前", (int)Math.Floor(span.TotalSeconds));
        }
        else
        {
            return "1秒前";
        }
    }
    #endregion

    #region 得到随机日期
    /// <summary>
    /// 得到随机日期
    /// </summary>
    /// <param name="time1">起始日期</param>
    /// <param name="time2">结束日期</param>
    /// <returns>间隔日期之间的 随机日期</returns>
    public static DateTime GetRandomTime(DateTime time1, DateTime time2)
    {
        Random random = new Random();
        DateTime min_time = new DateTime();
        DateTime max_time = new DateTime();

        if (time1 == default(DateTime) || time2 == default(DateTime))
            return default(DateTime);

        System.TimeSpan ts = new System.TimeSpan(time1.Ticks - time2.Ticks);

        // 获取两个时间相隔的秒数
        double total_secontds = ts.TotalSeconds;
        int i_total_secontds = 0;

        if (total_secontds > System.Int32.MaxValue)
        {
            i_total_secontds = System.Int32.MaxValue;
        }
        else if (total_secontds < System.Int32.MinValue)
        {
            i_total_secontds = System.Int32.MinValue;
        }
        else
        {
            i_total_secontds = (int)total_secontds;
        }


        if (i_total_secontds > 0)
        {
            min_time = time2;
            max_time = time1;
        }
        else if (i_total_secontds < 0)
        {
            min_time = time1;
            max_time = time2;
        }
        else
        {
            return time1;
        }

        int max_value = i_total_secontds;

        if (i_total_secontds <= System.Int32.MinValue)
            max_value = System.Int32.MinValue + 1;

        int i = random.Next(System.Math.Abs(max_value));

        return min_time.AddSeconds(i);
    }
    #endregion

    /// <summary>
    /// 获取日期是当月的第几周
    /// </summary>
    /// <param name="day"></param>
    /// <param name="week_start">1表示 周一至周日 为一周 2表示 周日至周六 为一周</param>
    /// <returns></returns>
    public static int WeekOfMonth(this DateTime day, int? week_start =1)
    {
        if (day == default(DateTime))
            return 0;

        DateTime first_of_month;
        first_of_month = Convert.ToDateTime(day.Date.Year + "-" + day.Date.Month + "-" + 1);

        int i = (int)first_of_month.Date.DayOfWeek;
        if (i == 0)
        {
            i = 7;
        }

        if (week_start == 1)
        {
            return (day.Date.Day + i - 2) / 7 + 1;
        }
        if (week_start == 2)
        {
            return (day.Date.Day + i - 1) / 7;

        }
        return 0;
        //错误返回值0
    }

    /// <summary>
    /// 获取以0点0分0秒开始的日期
    /// </summary>
    /// <param name="d"></param>
    /// <returns></returns>
    public static DateTime GetStartDateTime(this DateTime d)
    {
        if (d.Hour != 0)
        {
            var year = d.Year;
            var month = d.Month;
            var day = d.Day;
            var hour = "0";
            var minute = "0";
            var second = "0";
            d = Convert.ToDateTime(string.Format("{0}-{1}-{2} {3}:{4}:{5}", year, month, day, hour, minute, second));
        }
        return d;
    }

    /// <summary>
    /// 获取以23点59分59秒结束的日期
    /// </summary>
    /// <param name="d"></param>
    /// <returns></returns>
    public static DateTime GetEndDateTime(this DateTime d)
    {
        if (d.Hour != 23)
        {
            var year = d.Year;
            var month = d.Month;
            var day = d.Day;
            var hour = "23";
            var minute = "59";
            var second = "59";
            d = Convert.ToDateTime(string.Format("{0}-{1}-{2} {3}:{4}:{5}", year, month, day, hour, minute, second));
        }
        return d;
    }

    #region 时间戳

    /// <summary>
    /// 获取10位当前时间戳
    /// </summary>
    /// <returns></returns>
    public static long GetTimeStamp()
    {
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        return Convert.ToInt64(ts.TotalSeconds);
    }
    /// <summary>
    /// 获得13位当前时间戳
    /// </summary>
    /// <returns></returns>
    public static long GetLongTimeStamp()
    {
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        return Convert.ToInt64(ts.TotalMilliseconds);
    }

    /// <summary>
    /// 时间戳转为C#格式时间
    /// </summary>
    /// <param name=”time_stamp”></param>
    /// <returns></returns>
    public static DateTime ToDateTime(this string time_stamp)
    {
        if(string.IsNullOrEmpty(time_stamp) || string.IsNullOrWhiteSpace(time_stamp))
            return default(DateTime);
        DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
        long lTime = long.Parse(time_stamp + "0000000");
        TimeSpan toNow = new TimeSpan(lTime);
        return dtStart.Add(toNow);
    }
    /// <summary>
    /// DateTime时间格式转换为Unix时间戳格式
    /// </summary>
    /// <param name=”time”></param>
    /// <returns></returns>
    public static string ToTimeStamp(this System.DateTime time)
    {
        System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
        return Convert.ToString((int)(time - startTime).TotalSeconds);
    }



    #endregion


}
